﻿//+--------------------------------------------------------------------------------------------------
//     
//Description: Resource Extension Definition .NET objects used in JSON Ser/Deserialization
//Author: Aravind Ramarathinam (aravr@microsoft.com)
//Copyright © Microsoft Corporation
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
//INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
// 
//--------------------------------------------------------------------------------------------------------------------------------------------------------

using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Web.Script.Serialization;

namespace VmroleAuthor.Models
{
    [DataContract]
    public class VMRoleResourceExtensionDefinition
    {
        public const string ExpectedType = "Microsoft.Compute/EnterpriseApplicationExtension/1.0";
        public const string ExpectedSchemaVersion = "1.0";

        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Name { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Version { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Publisher { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string SchemaVersion { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]      
        public string Type { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public DataPackage DataPackage { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<Parameter> ResourceExtensionParameters { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public ResourceRequirements ResourceRequirements { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public ExtensionSettings ExtensionSettings { get; set; }
    }

    #region DataPackage
    [DataContract]
    public class DataPackage 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Version { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Location { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<ExternalPayload> ExternalPayload { get; set; }
    }
    [DataContract]
    public class ExternalPayload
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string RelativePath { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string Hash { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string URLHint { get; set; }
    }
    #endregion DataPackage   

    #region CONTAINER REQUIREMENTS   

    [DataContract]
    public class ResourceRequirements 
    {
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<string> OSVirtualHardDiskRequirements { get; set; }
    }
    #endregion CONTAINER REQUIREMENTS

    #region APPLICATION PROFILE
    [DataContract]
    public class ApplicationPayload 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string ID { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string RelativePath { get; set; }
    }

    #region SQL PROFILE

    public enum SQLAuthenticationType
    {
        SQLServerAuthentication,
        WindowsAuthentication,
    }
    [DataContract]
    public class SQLProfile 
    {
        [DataMember(IsRequired = true)]
        public List<SQLDeployment> SQLDeployments;
    }
      
    [DataContract]
    public class SQLDeployment 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string InstanceName { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string InstanceID { get; set; }
        [DataMember(IsRequired = true)]
        public string EnableNamedPipes { get; set; } //  bool
        [DataMember(IsRequired = true)]
        public string EnableTCP { get; set; } // bool 
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string MediaSource { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ProductKey { get; set; }
      
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string SQLAuthenticationType;  //SQLAuthenticationType
      

        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string SQLSysAdminMemberList { get; set; }
        [DataMember(IsRequired = true)]
        public string DeploymentTimeoutInSeconds { get; set; }  // int
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SQLConfigurationFilePayloadId { get; set; }  // Guid?
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SAPassword { get; set; }
        /// <summary>
        /// If Null, Default is "NT AUTHORITY\LocalSystem"
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SQLDeploymentCredential { get; set; }
        /// <summary>
        /// Default is "NT AUTHORITY\LocalSystem" 
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SQLAgentServiceCredential { get; set; }
        /// <summary>
        /// Default is "NT AUTHORITY\LocalSystem"
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SQLServiceCredential { get; set; }
        /// <summary>
        /// Default is "NT AUTHORITY\LocalSystem"
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SQLReportingServiceCredential { get; set; }                           
    }
    #endregion SQL PROFILE

    #region PROVISIONING SCRIPT

    public enum ProvisioningScriptType
    {
        PreInstall,
        PostInstall,
        PreService,
        PostService,
        PreUninstall,
        PostUninstall,
        OnProvisionFirst,
        OnProvisionRest,
        OnDeleteLast,
        OnDeleteRest,
        Install,
    }
    public enum ProvisioningScriptExecutionPolicy
    {
        FailOnMatch,
        WarnAndContinueOnMatch
    }
    [DataContract]
    public class ExecutableAndParams 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = true)]
        public string Executable { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = true)]
        public string Parameters { get; set; }
    }
    [DataContract]
    public class ProvisioningScript 
    {
        /// <summary>
        /// bool
        /// </summary>
        [DataMember(IsRequired = true)]
        public string AlwaysReboot { get; set; } 

        /// <summary>
        /// Guid?
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ApplicationPayloadId { get; set; }

        /// <summary>
        /// int?
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]       
        public string DeploymentOrder { get; set; }

        /// <summary>
        /// ProvisioningScriptExecutionPolicy 
        /// </summary>
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string ErrorPolicy;     

        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public ExecutableAndParams ExecutableAndParams { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ExitCodeRegex { get; set; }
        
        /// <summary>
        /// string
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string MaxOutputSize { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string RebootExitCodeRegex { get; set; }
        
        /// <summary>
        /// bool
        /// </summary>
        [DataMember(IsRequired = true)]
        public string RestartOnRetry { get; set; }

        /// <summary>
        /// bool
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string RestartOnExitCodeReboot { get; set; }

        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ScriptBlock { get; set; }
        
        /// <summary>
        /// ProvisioningScriptType 
        /// </summary>     
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string ScriptType { get; set; }

        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ScriptCredential { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardErrorPath { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardErrorRegex { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardInput { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardOutputPath { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardOutputRegex { get; set; }
        
        /// <summary>
        /// int
        /// </summary>
        [DataMember(IsRequired = true)]      
        public string TimeoutInSeconds { get; set; }
        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string WorkingDirectory { get; set; }

        [OnSerializing]
        private void SetValuesOnSerializing(StreamingContext context)
        {
            if (this.ExecutableAndParams != null)
            {
                if (this.ExecutableAndParams.Executable == null && this.ExecutableAndParams.Parameters == null)
                {
                    this.ExecutableAndParams = null;
                }
                else if (this.ExecutableAndParams.Executable != null && this.ExecutableAndParams.Parameters == null)
                {
                    this.ExecutableAndParams.Parameters = string.Empty; //work around a product bug
                }
            }
        }
    }
    #endregion PROVISIONING SCRIPT

    #region WEB DEPLOY APPLICATION    
    [DataContract]
    public class WebDeploymentParameters 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string ParameterName { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Value { get; set; }       
    }
    [DataContract]
    public class WebDeployApplication 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string DeploymentName { get; set; }
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string ApplicationPayloadId { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string PackagePassword { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<ProvisioningScript> ScriptCommands { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<WebDeploymentParameters> WebDeploymentParameters { get; set; }
    }
    #endregion WEB DEPLOY APPLICATION

    #region SQL DAC APPLICATION
    public enum SQLScriptType
    {
        PreInstall,
        PostInstall,
        PreService,
        PostService,
        PreUninstall,
        PostUninstall,
    }    
    public enum DACUninstallModeType
    {
        DetachDatabase,
        DropDatabase,
        MakeUnmanaged,
    }    
    
    [DataContract]
    public class SQLScriptCommand 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string DatabaseName { get; set; }
        [DataMember(IsRequired = true)]
        public string DeploymentOrder { get; set; } //int
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string CommandParameters { get; set; }
        [DataMember(IsRequired = true)]
        public string EncryptConnection { get; set; } // bool
        [DataMember(IsRequired = true)]
        public string ExecutionTimeoutSeconds { get; set; } //int
        [DataMember(IsRequired = true)]
        public string LoginTimeoutSeconds { get; set; } //int
        [DataMember(IsRequired = false)]
        public string OutputFilePath { get; set; }

        [DataMember(IsRequired = false, EmitDefaultValue = false)] 
        public string SQLAuthenticationType;  // SQLAuthenticationType
           
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string SQLScriptApplicationPayloadId { get; set; } // Guid

        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string ScriptCredential { get; set; }

        [DataMember(IsRequired = true, EmitDefaultValue = false)] 
        public string ScriptType; // SQLScriptType
    }

    [DataContract]
    public class SQLDacApplication 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string DeploymentName { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<ProvisioningScript> ScriptCommands { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<SQLScriptCommand> SQLScriptCommands { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ApplicationPayloadId { get; set; } // Guid
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string DacInstance { get; set; }       
        [DataMember(IsRequired = false, EmitDefaultValue = false)]  
        public string SQLAuthenticationType; //  SQLAuthenticationType            
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SQLDeploymentCredential { get; set; }
        [DataMember(IsRequired = true)]
        public string BlockOnChanges { get; set; } //bool
        [DataMember(IsRequired = true)]
        public string IgnoreDataLoss { get; set; } //bool
        [DataMember(IsRequired = true)]
        public string RollbackOnFailure { get; set; }  //bool      
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string SQLInstance { get; set; }
        [DataMember(IsRequired = true)]
        public string SkipPolicyValidation { get; set; } //bool             
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string UninstallMode;     // DACUninstallModeType   
    }
    #endregion SQL DAC APPLICATION

    #region SCRIPT APPLICATION
    [DataContract]
    public class ScriptApplication 
    {
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<ProvisioningScript> ScriptCommands { get; set; }

        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<EnvironmentVariable> EnvironmentVariables { get; set; }

        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string DeploymentName { get; set; }
        [DataMember(IsRequired = true)]
        public string AlwaysReboot { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ApplicationPayloadId { get; set; }      
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string ErrorPolicy { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public ExecutableAndParams ExecutableAndParams { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ExitCodeRegex { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string MaxOutputSize { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string RebootExitCodeRegex { get; set; }
        /// <summary>
        /// bool
        /// </summary>
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string RestartOnExitCodeReboot { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ScriptBlock { get; set; }        
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string ScriptCredential { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardErrorPath { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardErrorRegex { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardInput { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardOutputPath { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string StandardOutputRegex { get; set; }
        [DataMember(IsRequired = true)]
        public string TimeoutInSeconds { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public string WorkingDirectory { get; set; }

        [OnSerializing]
        private void SetValuesOnSerializing(StreamingContext context)
        {
            if (this.ExecutableAndParams != null)
            {
                if (this.ExecutableAndParams.Executable == null && this.ExecutableAndParams.Parameters == null)
                {
                    this.ExecutableAndParams = null;
                }
                else if (this.ExecutableAndParams.Executable != null && this.ExecutableAndParams.Parameters == null)
                {
                    this.ExecutableAndParams.Parameters = string.Empty; //work around a product bug
                }                
            }
        }
    }
    #endregion

    #region ENVIRONMENT VARIABLE
    [DataContract]
    public class EnvironmentVariable 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Name { get; set; }

        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Value { get; set; }
    }
    #endregion

   

    #region WINDOWS APPLICATION PROFILE
    [DataContract]
    public class WindowsApplicationProfile 
    {
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<string> WindowsServerRolesAndFeatures { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public SQLProfile SQLProfile { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<ProvisioningScript> ProvisioningScripts { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<WebDeployApplication> WebDeployApplications { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<SQLDacApplication> SQLDacApplications { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<ScriptApplication> ScriptApplications { get; set; }
    }
    #endregion WINDOWS APPLICATION PROFILE

    #region LINUX APPLICATION PROFILE
   

    [DataContract]
    public class LinuxApplicationProfile
    {
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<string> RunOnceCommands { get; set; }

        private List<StringHolder> runOnceCommandHolders;      

        [ScriptIgnore]
        public List<StringHolder> RunOnceCommandHolders
        {
            get
            {
                if (this.runOnceCommandHolders == null)
                {
                    this.runOnceCommandHolders = new List<StringHolder>();
                    if (this.RunOnceCommands != null)
                    {
                        foreach (string runOnceCommand in RunOnceCommands)
                        {
                            this.runOnceCommandHolders.Add(new StringHolder { Value =  runOnceCommand });
                        }
                    }
                }
                return this.runOnceCommandHolders;
            }
            set { this.runOnceCommandHolders = value; }
        }

        [OnSerializing]
        private void SetValuesOnSerializing(StreamingContext context)
        {            
            if (this.runOnceCommandHolders != null)
            {
                this.RunOnceCommands = new List<string>();
                foreach (StringHolder runOnceCommandHolder in RunOnceCommandHolders)
                {
                    if (!string.IsNullOrEmpty(runOnceCommandHolder.Value))
                    {
                        this.RunOnceCommands.Add(runOnceCommandHolder.Value);
                    }                    
                }
            }
        }
    }
    #endregion LINUX APPLICATION PROFILE

    [DataContract]
    public class ExtensionSettings 
    {             
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public ApplicationProfile ApplicationProfile { get; set; }
    }

    [DataContract]
    public class ApplicationProfile 
    {
        [DataMember(IsRequired = true, EmitDefaultValue = false)]
        public string Name { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public List<ApplicationPayload> ApplicationPayload { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public WindowsApplicationProfile WindowsApplicationProfile { get; set; }
        [DataMember(IsRequired = false, EmitDefaultValue = false)]
        public LinuxApplicationProfile LinuxApplicationProfile { get; set; }
    }
    #endregion APPLICATION PROFILE    
}
